package middleware

import (
	"net/http"
	"strconv"
	"strings"

	"github.com/gin-gonic/gin"
)

// CORSConfig 定义CORS配置
type CORSConfig struct {
	// 允许的源站列表，例如: ["http://localhost:3000", "https://example.com"]
	AllowOrigins []string

	// 允许的HTTP方法列表
	AllowMethods []string

	// 允许的请求头列表
	AllowHeaders []string

	// 是否允许携带凭证信息（cookies等）
	AllowCredentials bool

	// 预检请求的有效期（秒）
	MaxAge int
}

// DefaultCORSConfig 默认CORS配置
var DefaultCORSConfig = CORSConfig{
	AllowOrigins: []string{"*"},
	AllowMethods: []string{"GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"},
	AllowHeaders: []string{
		"Origin", "Content-Length", "Content-Type", "Authorization",
		"X-Requested-With", "X-Auth-Token", "X-CSRF-Token",
	},
	AllowCredentials: false,
	MaxAge:           12 * 3600, // 12小时
}

// Cors 创建CORS中间件
func Cors() gin.HandlerFunc {
	return CorsWithConfig(DefaultCORSConfig)
}

// CorsWithConfig 使用自定义配置创建CORS中间件
func CorsWithConfig(config CORSConfig) gin.HandlerFunc {
	// 处理默认值
	if len(config.AllowOrigins) == 0 {
		config.AllowOrigins = DefaultCORSConfig.AllowOrigins
	}
	if len(config.AllowMethods) == 0 {
		config.AllowMethods = DefaultCORSConfig.AllowMethods
	}
	if len(config.AllowHeaders) == 0 {
		config.AllowHeaders = DefaultCORSConfig.AllowHeaders
	}
	if config.MaxAge <= 0 {
		config.MaxAge = DefaultCORSConfig.MaxAge
	}

	// 将切片转换为字符串
	allowOrigins := strings.Join(config.AllowOrigins, ", ")
	allowMethods := strings.Join(config.AllowMethods, ", ")
	allowHeaders := strings.Join(config.AllowHeaders, ", ")
	maxAge := strconv.Itoa(config.MaxAge)

	return func(c *gin.Context) {
		origin := c.Request.Header.Get("Origin")

		// 检查请求源是否被允许
		if isOriginAllowed(origin, config.AllowOrigins) {
			c.Header("Access-Control-Allow-Origin", origin)
		} else if allowOrigins == "*" {
			c.Header("Access-Control-Allow-Origin", "*")
		}

		// 设置其他CORS头
		c.Header("Access-Control-Allow-Methods", allowMethods)
		c.Header("Access-Control-Allow-Headers", allowHeaders)

		if config.AllowCredentials {
			c.Header("Access-Control-Allow-Credentials", "true")
		}

		c.Header("Access-Control-Max-Age", maxAge)

		// 处理预检请求
		if c.Request.Method == "OPTIONS" {
			c.Header("Access-Control-Allow-Methods", allowMethods)
			c.Header("Access-Control-Allow-Headers", allowHeaders)
			c.AbortWithStatus(http.StatusNoContent)
			return
		}

		c.Next()
	}
}

// isOriginAllowed 检查请求源是否被允许
func isOriginAllowed(origin string, allowOrigins []string) bool {
	if origin == "" {
		return false
	}

	for _, allowedOrigin := range allowOrigins {
		if allowedOrigin == "*" || allowedOrigin == origin {
			return true
		}
	}

	return false
}
